home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / manageme / tcpdump-.001 / tcpdump-~ / tcpdump-3.0.2-linux / libpcap-0.0.6 / pcap-linux.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-30  |  4.3 KB  |  194 lines

  1. /*
  2.  * Linux interface for packet capture lib
  3.  * ported by Adam Caldwell (acaldwel@ace.cs.ohiou.edu)
  4.  * Based on the pcap-snoop.c file
  5.  * May be freely redistributed as per the GNU license
  6.  */
  7. #include <sys/param.h>
  8. #include <stdio.h>
  9. #include <netdb.h>
  10. #include <ctype.h>
  11. #include <signal.h>
  12. #include <errno.h>
  13. #include <sys/time.h>
  14. #include <sys/socket.h>
  15. #include <sys/file.h>
  16. #include <sys/ioctl.h>
  17. #include <malloc.h>
  18. #include <memory.h>
  19. #include <unistd.h>
  20.  
  21.  
  22. #include <net/if.h>
  23. #include <net/if_arp.h>
  24. #include <netinet/in.h>
  25. #include <netinet/in_systm.h>
  26. #include <netinet/ip.h>
  27. #include <netinet/ip_var.h>
  28. #include <netinet/udp.h>
  29. #include <netinet/tcp.h>
  30. #include <net/bpf.h>
  31.  
  32. #include "pcap-int.h"
  33.  
  34. static char snoop_device[255];
  35. struct ifreq ifr_orig;
  36.  
  37. void restore_interface()
  38. {
  39.   int fd;
  40.  
  41.   fd = socket(PF_INET, SOCK_PACKET, htons(0x0003));
  42.   if (fd < 0) {
  43.     printf("Warning: could not restore interface to normal.\n");
  44.     return;
  45.   }
  46.  
  47.   if (ioctl(fd, SIOCSIFFLAGS, &ifr_orig)<0)
  48.     printf("Warning: could not restore interface to normal.\n");
  49. }
  50.  
  51. int pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
  52. {
  53.   register int datalen;
  54.   register int caplen;
  55.   struct sockaddr from;
  56.   int from_len;
  57.   char *buf;
  58.   int bufsize;
  59.  
  60.   if (p->linktype == DLT_SLIP) {
  61.     buf = (char *)p->buffer+16;
  62.     bufsize = p->bufsize - 16;
  63.     memset(p->buffer,0,16);
  64.   } else if (p->linktype == DLT_PPP) {
  65.     buf = (char *)p->buffer+4;
  66.     bufsize = p->bufsize - 4;
  67.     memset(p->buffer,0,4);
  68.   } else {
  69.     buf = (char *)p->buffer;
  70.     bufsize = p->bufsize;
  71.   }
  72.  
  73.   do {
  74.     from_len = sizeof(from);
  75.     datalen = recvfrom(p->fd,buf,bufsize,0,&from,&from_len);
  76.  
  77.     if (datalen < 0) {
  78.       switch (errno) {
  79.     case EWOULDBLOCK:
  80.       return (0);
  81.       }
  82.       sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
  83.       return (-1);
  84.     }
  85.   } while (strcmp(snoop_device,from.sa_data)); /* go until we find something
  86.                          from the right interface */
  87.  
  88.   if (p->linktype == DLT_SLIP)
  89.     datalen+=16;
  90.   else if (p->linktype == DLT_PPP)
  91.     datalen+=4;
  92.  
  93.   caplen = (datalen > p->bufsize) ? datalen : p->bufsize;
  94.  
  95.   if (caplen > p->snapshot)
  96.     caplen = p->snapshot;
  97.  
  98.   if (p->fcode.bf_insns == NULL ||
  99.       bpf_filter(p->fcode.bf_insns, (char *)p->buffer, datalen, caplen)) {
  100.     struct pcap_pkthdr h;
  101.     ++p->md.stat.ps_recv;
  102.  
  103. #ifdef SIOCGSTAMP
  104.     if (ioctl(p->fd,SIOCGSTAMP,&h.ts)<0) /* ask for the timestamp */
  105. #endif
  106.       gettimeofday(&h.ts,0);
  107.  
  108.     h.len = datalen;
  109.     h.caplen = caplen;
  110.     (*callback)(user, &h, (char *)p->buffer);
  111.     return (1);
  112.   }
  113.   return (0);
  114. }
  115.  
  116. int pcap_stats(pcap_t *p, struct pcap_stat *ps)
  117. {
  118.   ps->ps_drop = 0;
  119.   ps->ps_recv = p->md.stat.ps_recv;
  120.   ps->ps_ifdrop = 0;
  121.   return (0);
  122. }
  123.  
  124. pcap_t *
  125. pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
  126. {
  127.   pcap_t *p;
  128.   struct ifreq ifr;
  129.  
  130.   p = (pcap_t *)malloc(sizeof(*p));
  131.   if (p == NULL) {
  132.     strcpy(ebuf, "no swap");
  133.     return (0);
  134.   }
  135.   bzero(p, sizeof(*p));
  136.   if (strncmp("et", device, 2) == 0)
  137.     p->linktype = DLT_EN10MB;
  138.   else if (strncmp("sl", device, 2) == 0)
  139.     p->linktype = DLT_SLIP;
  140.   else if (strncmp("pp", device, 2) == 0)
  141.     p->linktype = DLT_PPP;
  142.   else {
  143.     sprintf(ebuf, "snoop: unknown physical layer type");
  144.     goto bad;
  145.   }
  146.   p->fd = -1;
  147.   p->bufsize = 4096;
  148.   p->buffer = (u_char *)malloc(p->bufsize);
  149.   if (p->buffer == NULL) {
  150.     strcpy(ebuf, "no swap");
  151.     goto bad;
  152.   }
  153.   p->fd = socket(PF_INET, SOCK_PACKET, htons(0x0003));
  154.   if (p->fd < 0) {
  155.     sprintf(ebuf, "snoop socket: %s", pcap_strerror(errno));
  156.     goto bad;
  157.   }
  158.  
  159.   if (p->linktype != DLT_SLIP && p->linktype != DLT_PPP && promisc) {
  160.     strcpy(ifr.ifr_name, device);       /* interface we're gonna use */
  161.     if (ioctl(p->fd, SIOCGIFFLAGS, &ifr) < 0 ) {    /* get flags */
  162.       sprintf(ebuf, "socket ioctl get: %s", pcap_strerror(errno));
  163.       goto bad;
  164.     }
  165.     ifr_orig = ifr;
  166.     atexit(restore_interface);
  167.     ifr.ifr_flags |= IFF_PROMISC;         /* set promiscuous mode */
  168.  
  169.     if (ioctl(p->fd, SIOCSIFFLAGS, &ifr) < 0 ) {    /* set flags */
  170.       sprintf(ebuf, "socket ioctl set: %s", pcap_strerror(errno));
  171.       goto bad;
  172.     }
  173.   }
  174.   strcpy(snoop_device,device);
  175.  
  176.   p->snapshot = snaplen;
  177.   return (p);
  178. bad:
  179.   if (p->fd >= 0)
  180.       close(p->fd);
  181.   if (p->buffer != NULL)
  182.       free(p->buffer);
  183.   free(p);
  184.   return (0);
  185. }
  186.  
  187. int
  188. pcap_setfilter(pcap_t *p, struct bpf_program *fp)
  189. {
  190.  
  191.     p->fcode = *fp;
  192.     return (0);
  193. }
  194.